package com.sale.plugins;

import com.apache.api.manager.ProxyManager;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.database.constant.SpringContextLoader;
import com.apache.exception.BusinessException;
import com.apache.ius.plugin.CustomMethodPlugin;
import com.apache.ius.plugin.UtilPlugin;
import com.apache.match.common.Constant;
import com.apache.tools.DataMap;
import com.apache.tools.DateUtils;
import com.apache.tools.NumberUtils;
import org.apache.log4j.Logger;

import java.util.*;

/**
 * 发售交易-申购配号：
 * 1.根据规则生成配号（时间Long+最大配号数）
 * 2.给每个申购人分配配号。
 *
 * @author admin
 */
public class SaleAllocationNumberPluginImpl implements CustomMethodPlugin {

    private Logger log = Logger.getLogger(getClass());

    @Override
    public Object beforeInvoke(Map<String, Object> param) {
        log.info("start->> 【发售交易】生成配号并分配");
        log.info("start->> 接收参数：" + param);
        String saleId = String.valueOf(param.get("trsSale.w_saleId"));
        if (Validator.isNull(saleId)) {
            throw new BusinessException("saleId参数缺失！");
        }
        //1.查询发行活动对象
        DataMap saleMap = getSaleInfo(param, saleId);
        if (saleMap == null || saleMap.size() < 1) {
            throw new BusinessException("未找到发行活动");
        }
        //2.获取相关参数。
        String proId = String.valueOf(saleMap.get("proId"));
        String proNo = String.valueOf(saleMap.get("proNo"));
        String proName = String.valueOf(saleMap.get("proName"));
        String buyTotalNum = String.valueOf(saleMap.get("buyTotalNum"));
        ;//此活动实际申购总数量
        String buyUserCount = String.valueOf(saleMap.get("buyUserCount"));
        ;//此活动实际申购用户总数
        String minChangeNum = String.valueOf(saleMap.get("minChangeNum"));
        ;//此活动规则：最小变动单位
        String price = String.valueOf(saleMap.get("priceInit"));
        ;//此活动规则：发行价格

        //3.获取申购列表
        List<DataMap> buyListMap = getBuyListData(param, saleId);

        long totalPurchaseNum = Long.valueOf(buyTotalNum);//申购数量总和
        long minPurchaseNum = Long.valueOf(minChangeNum);//最小申购变动量

        //4.计算出本次最大配号数（申购总数量/最小变动单位）
        long totalAllocationNumber = Math
                .round(NumberUtils.divide(totalPurchaseNum, minPurchaseNum, 2));
        log.info("本次需配号总个数：" + totalAllocationNumber);
        if (totalAllocationNumber < 1) {
            throw new BusinessException("配号失败，无需配号！");
        }
        //5.开始配号
        //时间
        long timeLong = new Date().getTime();
        //时间Long（string）
        String timeStr = String.valueOf(timeLong);
        int tanLength = (totalAllocationNumber + "").length();

        int i = 0;
        String allocationNumber = "";

        //6.遍历申购记录
        for (DataMap buyMap : buyListMap) {

            String num = String.valueOf(buyMap.get("num"));
            String buyId = String.valueOf(buyMap.get("buyId"));
            String userId = String.valueOf(buyMap.get("userId"));
            String userOwner = String.valueOf(buyMap.get("userOwner"));
            String userCname = String.valueOf(buyMap.get("userRealName"));

            //计算每个申购交易用户需要配的号码个数
            long count = Math.round(NumberUtils.divide(Long.parseLong(num), minPurchaseNum, 2));
            log.info("给[" + userOwner + "-" + userCname + "]需要配[" + count + "]个号！");

            //生成配号
            for (int j = 1; j <= count; j++) {
                //新生成尾号
                String newStr = i + "";
                //新生成尾号长度
                int newNumLength = newStr.length();
                //新生成尾号长度等于最大配号长度，新生成尾号不补位
                if (newNumLength == tanLength) {
                    allocationNumber = timeStr + newStr;
                } else {
                    //新生成浩长度小于最大配号长度，新生成配号补位
                    while (newNumLength < tanLength) {
                        newStr = "0" + newStr;
                        newNumLength++;
                    }
                    allocationNumber = timeStr + newStr;
                }
                Map<String, Object> numbersMap = new HashMap<String, Object>();
                numbersMap.put("datasource",param.get("datasource"));
                numbersMap.put("trsNumbers.createTime", DateUtils.getNow());
                numbersMap.put("trsNumbers.price", price);
                numbersMap.put("trsNumbers.nums", minPurchaseNum);
                numbersMap.put("trsNumbers.proId", proId);
                numbersMap.put("trsNumbers.proNo", proNo);
                numbersMap.put("trsNumbers.proName", proName);
                numbersMap.put("trsNumbers.userId", userId);
                numbersMap.put("trsNumbers.saleId", saleId);
                numbersMap.put("trsNumbers.buyerId", buyId);
                numbersMap.put("trsNumbers.randNumber", allocationNumber);
                numbersMap.put("trsNumbers.sysName", "sale");
                numbersMap.put("trsNumbers.userOwner", userOwner);
                numbersMap.put("trsNumbers.isSelect", "F");
                numbersMap.put("trsNumbers.isPay", "F");
                numbersMap.put("trsNumbers.userCname", userCname);
                numbersMap.put("trsNumbers.remark", "配号完成，等待摇号");

                saveNumbers(numbersMap);

                newNumLength++;
                //TODO保存数据 saveTrsNumber
                i++;
            }
        }

        //补充发行活动trsSale的其他参数
        param.put("trsSale.buyNum", totalPurchaseNum);//申购总数量
        param.put("trsSale.buyUser", buyUserCount);//申购用户个数
        param.put("trsSale.numCount", totalAllocationNumber);//配号个数

        Map<String, Object> trsBuyMap = new HashMap<String, Object>();
        trsBuyMap.put("datasource",param.get("datasource"));
        trsBuyMap.put("trsBuy.w_saleId", saleId);
        trsBuyMap.put("trsBuy.buyStatus", "20");
        saveBuyStatus(trsBuyMap);
        return null;
    }

    @Override
    public Object doInvoke(Map<String, Object> param) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object afterInvoke(Map<String, Object> param) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 【未使用】查询申购活动sale对象
     *
     * @param param
     * @param saleId
     * @return
     */
    @SuppressWarnings("rawtypes")
    public DataMap getSaleData(Map<String, Object> param, String saleId) {
//        ProxyManager netProxyManager = (ProxyManager) SpringContextLoader
//                .getBean("netProxyManager");
//        ParamsVo params = new ParamsVo();
//        params.setParams("doCode", "dymicSql");
//        params.setParams("sqlKeyId", "ByDymicSql");
//        params.setParams("resultType", "objInfo");
//        params.setParams("resultObjType", "obj");
//        params.setKey("publicForSql");
//
//        //封装参数
//        params.setParams("modelTypes", "s_trsSale");
//        params.setParams("trsSale.w_saleId", saleId);
        Map<String, Object> whereMap =  new HashMap<String,Object>();
        whereMap.put("trsSale.w_saleId", saleId);
        ResultEntity dymicSqlParamResult = UtilPlugin.getInstance().selectInfoForDatasource(String.valueOf(param.get("datasource")),"s_trsSale","obj",whereMap);
        DataMap dm = (DataMap) dymicSqlParamResult.getEntity();
        return dm;
    }

    /**
     * 查询所有交易商的申购列表
     *
     * @param param
     * @param saleId
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List<DataMap> getBuyListData(Map<String, Object> param, String saleId) {
//        ProxyManager netProxyManager = (ProxyManager) SpringContextLoader
//                .getBean("netProxyManager");
//        ParamsVo params = new ParamsVo();
//        params.setParams("doCode", "dymicSql");
//        params.setParams("sqlKeyId", "ByDymicSql");
//        params.setParams("resultType", "objInfo");
//        params.setKey("publicForSql");
//
//        //封装参数
//        params.setParams("modelTypes", "s_trsBuy");
//        params.setParams("trsBuy.w_saleId", saleId);

        Map<String, Object> whereMap =  new HashMap<String,Object>();
        whereMap.put("trsBuy.w_saleId", saleId);
        List<DataMap> list  = UtilPlugin.getInstance().getListByParams(String.valueOf(param.get("datasource")),"s_trsBuy",whereMap);

        return list;
    }

    /**
     * 【未使用】 获取此发行活动的申购总数量，sum(trsBuy.num)
     *
     * @param param
     * @param saleId
     * @return
     */
    @SuppressWarnings("rawtypes")
    public long getBuySumNum(Map<String, Object> param, String saleId) {
//        ProxyManager netProxyManager = (ProxyManager) SpringContextLoader
//                .getBean("netProxyManager");
//        ParamsVo params = new ParamsVo();
        String returnKeyName = "totalnum";
//        params.setParams("sqlKeyId", "ByObjInfo");
//        params.setKey("publicForSql");

        String dataType = Constant.getDatabaseType("sale");
        String dyncSql ="";
        if("oracle".equals(dataType)){
            dyncSql = "select sum(b.num) as " + returnKeyName
                    + " from trs_buy b where 1=1 and b.sale_id='" + saleId + "'";
        }else{
            dyncSql = "select cast(sum(b.num) as signed) as " + returnKeyName
                    + " from trs_buy b where 1=1 and b.sale_id='" + saleId + "'";
        }


//        params.setParams("dyncSql", dyncSql);
//        ResultEntity dymicSqlParamResult = (ResultEntity) netProxyManager.doInvoke(params);
        List<DataMap> list = (List<DataMap>)UtilPlugin.getInstance().selectObjectForDatasource(dyncSql,"sale");

//        List<DataMap> list = (List) dymicSqlParamResult.getEntity();
        if (list != null && list.size() > 0) {
            DataMap numMap = list.get(0);
            if (numMap.containsKey(returnKeyName)) {
                String totalNum = String.valueOf(numMap.get(returnKeyName));
                totalNum = Validator.getDefaultStr(totalNum, "0");
                return Long.parseLong(totalNum);
            }
        }
        return 0;
    }

    /**
     * 综合查询：申购活动sale对象、申购总量、申购用户数、最小变动单位等
     *
     * @param param
     * @param saleId
     * @return
     */
    @SuppressWarnings("rawtypes")
    public DataMap getSaleInfo(Map<String, Object> param, String saleId) {
//        ProxyManager netProxyManager = (ProxyManager) SpringContextLoader
//                .getBean("netProxyManager");
//        ParamsVo params = new ParamsVo();
        String rulesNo = "sale01";//申购最小变动单位规则rulesNo
//        params.setParams("sqlKeyId", "ByObjInfo");
//        params.setKey("publicForSql");
        StringBuffer dyncSql = new StringBuffer("select s.*,");
        String dataType = Constant.getDatabaseType("sale");

        dyncSql.append("(select p.param_no from trs_rules_pro p where p.sale_id='" + saleId
                + "' and p.rules_no='" + rulesNo + "') as min_change_num ,");
        if("oracle".equals(dataType)){
            dyncSql.append("(select sum(t.num) from trs_buy t where t.sale_id='" + saleId
                    + "')  as buy_total_num,");//申购总数量
        }else{
            dyncSql.append("(select cast(sum(t.num) as signed) from trs_buy t where t.sale_id='" + saleId
                    + "')  as buy_total_num,");//申购总数量
        }
        dyncSql.append("(select count(*) from trs_buy t where t.sale_id='" + saleId
                + "')  as buy_user_count ");//申购总人数
        dyncSql.append(" from trs_sale s where  s.sale_id='" + saleId + "'");
//        params.setParams("dyncSql", dyncSql.toString());
        System.out.println("配号-查询发行活动SQL=>" + dyncSql);
//        ResultEntity dymicSqlParamResult = (ResultEntity) netProxyManager.doInvoke(params);
        List<DataMap> list = (List<DataMap>)UtilPlugin.getInstance().selectObjectForDatasource(dyncSql.toString(),"sale");

//        List<DataMap> list = (List) dymicSqlParamResult.getEntity();
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 保存配号结果
     *
     * @param numbersMap
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public List<DataMap> saveNumbers(Map<String, Object> numbersMap) {
//        ProxyManager netProxyManager = (ProxyManager) SpringContextLoader
//                .getBean("netProxyManager");
//        ParamsVo params = new ParamsVo();
//        params.setParams(numbersMap);
//        params.setParams("doCode", "dymicSql");
//        params.setParams("sqlKeyId", "ByDymicSql");
//        params.setParams("resultType", "processSql");
//        params.setKey("publicForSql");

        //封装参数
//        params.setParams("modelTypes", "i_trsNumbers");

//        ResultEntity dymicSqlParamResult = (ResultEntity) netProxyManager.doInvoke(params);
        ResultEntity dymicSqlParamResult = UtilPlugin.getInstance().saveByParams("sale","i_trsNumbers",numbersMap);


        Map result = (Map) dymicSqlParamResult.getEntity();
        log.info("[" + String.valueOf(numbersMap.get("trsNumbers.userOwner")) + "]-[" + String
                .valueOf(numbersMap.get("trsNumbers.randNumber")) + "]号码保存完成：" + result);
        return null;
    }

    /**
     * 保存配号结果级联sale表的状态
     *
     * @param trsBuyMap
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public List<DataMap> saveBuyStatus(Map<String, Object> trsBuyMap) {
//        ProxyManager netProxyManager = (ProxyManager) SpringContextLoader
//                .getBean("netProxyManager");
//        ParamsVo params = new ParamsVo();
//        params.setParams(trsBuyMap);
//        params.setParams("doCode", "dymicSql");
//        params.setParams("sqlKeyId", "ByDymicSql");
//        params.setParams("resultType", "processSql");
//        params.setKey("publicForSql");

        //封装参数
//        params.setParams("modelTypes", "u_trsBuy");

//        ResultEntity dymicSqlParamResult = (ResultEntity) netProxyManager.doInvoke(params);
        ResultEntity dymicSqlParamResult = UtilPlugin.getInstance().saveByParams(String.valueOf(trsBuyMap.get("datasource")),"u_trsBuy",trsBuyMap);

        Map result = (Map) dymicSqlParamResult.getEntity();
        log.info("[" + String.valueOf(trsBuyMap.get("trsBuy.w_saleId")) + "]-[" + String
                .valueOf(trsBuyMap.get("trsBuy.buyStatus")) + "]状态保存完成：" + result);
        return null;
    }

    /**
     * 规则校验入口（专门给系统公式规则提供的）
     *
     * @param paramsVo
     */
    public void run(ParamsVo paramsVo) {
        beforeInvoke(paramsVo.getParams());
    }

    public static void main(String[] args) {
        double totalPurchaseNum = NumberUtils.getDouble("101000", 0,true);//申购数量总和
        System.out.println(totalPurchaseNum);
        long totalAllocationNumber = Math.round(totalPurchaseNum);
        System.out.println(totalAllocationNumber);
    }

}
